package org.hiucung.hlsdownloader.utils

import org.hiucung.hlsdownloader.bean.EncryptionKey
import org.hiucung.hlsdownloader.bean.M3UItem
import org.hiucung.hlsdownloader.bean.M3UPlaylist
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
import java.net.URI
import java.net.URL

/**
 * @Classname M3U8Parser
 * @Description HLS M3U8解析器，支持加密key和iv解析
 * @Date 2025/8/21 10:18
 * @Created by Kicc
 */
class M3U8Parser {

    /**
     * 从文件解析 M3U
     */
    fun parseFile(file: File): M3UPlaylist {
        return parse(file.bufferedReader(), file.parent ?: "")
    }

    /**
     * 从 URL 解析 M3U
     */
    fun parseUrl(url: String): M3UPlaylist {
        val connection = URL(url).openConnection()
        val baseUrl = url.substringBeforeLast("/") + "/"
        val inputStream = connection.getInputStream()
        return parse(inputStream.bufferedReader(), baseUrl)
    }

    /**
     * 从输入流解析 M3U
     */
    fun parse(inputStream: InputStream, basePath: String = ""): M3UPlaylist {
        return parse(inputStream.bufferedReader(), basePath)
    }

    /**
     * 核心解析方法
     */
    private fun parse(reader: BufferedReader, basePath: String): M3UPlaylist {
        val items = mutableListOf<M3UItem>()
        var isExtended = false
        var version: Int? = null
        var targetDuration: Float? = null
        var playlistType: String? = null
        var currentGroup: String? = null
        var mediaSequence: Int? = null
        var endList: Boolean = false

        var currentDuration: Float? = null
        var currentTitle: String? = null
        var currentUrl: String? = null
        var currentKey: EncryptionKey? = null
        var currentDiscontinuity: Boolean = false

        reader.useLines { lines ->
            lines.forEach { line ->
                when {
                    // 检查是否是扩展 M3U 格式
                    line.startsWith("#EXTM3U") -> {
                        isExtended = true
                        // 尝试解析版本号
                        val versionMatch = Regex("VERSION=(\\d+)").find(line)
                        version = versionMatch?.groupValues?.get(1)?.toIntOrNull()
                    }

                    // 解析目标时长
                    line.startsWith("#EXT-X-TARGETDURATION") -> {
                        targetDuration = line.substringAfter(':').toFloatOrNull()
                    }

                    // 解析播放列表类型
                    line.startsWith("#EXT-X-PLAYLIST-TYPE") -> {
                        playlistType = line.substringAfter(':').trim()
                    }

                    // 解析媒体序列号
                    line.startsWith("#EXT-X-MEDIA-SEQUENCE") -> {
                        mediaSequence = line.substringAfter(':').toIntOrNull()
                    }

                    // 解析结束标记
                    line.startsWith("#EXT-X-ENDLIST") -> {
                        endList = true
                    }

                    // 解析不连续标记
                    line.startsWith("#EXT-X-DISCONTINUITY") -> {
                        currentDiscontinuity = true
                    }

                    // 解析分组标题
                    line.startsWith("#EXTGRP") -> {
                        currentGroup = line.substringAfter(':').trim().takeIf { it.isNotEmpty() }
                    }

                    // 解析加密Key
                    line.startsWith("#EXT-X-KEY") -> {
                        currentKey = parseEncryptionKey(line, basePath)
                    }

                    // 解析条目信息
                    line.startsWith("#EXTINF") -> {
                        val parts = line.substringAfter(':').split(',', limit = 2)
                        currentDuration = parts.getOrNull(0)?.toFloatOrNull()
                        currentTitle = parts.getOrNull(1)?.trim()?.takeIf { it.isNotEmpty() }
                    }

                    // 解析实际 URL
                    line.isNotBlank() && !line.startsWith("#") -> {
                        currentUrl = line.trim()
                        if (currentUrl != null) {
                            val isDirect = !(currentUrl!!.endsWith(".m3u") || currentUrl!!.endsWith(".m3u8"))

                            // 处理相对路径URL
                            val resolvedUrl = resolveUrl(currentUrl!!, basePath)

                            items.add(
                                M3UItem(
                                    duration = currentDuration,
                                    title = currentTitle,
                                    url = resolvedUrl,
                                    groupTitle = currentGroup,
                                    isDirect = isDirect,
                                    encryptionKey = currentKey,
                                    isDiscontinuity = currentDiscontinuity
                                )
                            )
                            // 重置当前条目信息（除了key，key会持续到下一个KEY标签）
                            currentDuration = null
                            currentTitle = null
                            currentUrl = null
                            currentDiscontinuity = false
                        }
                    }
                }
            }
        }

        return M3UPlaylist(
            items = items,
            isExtended = isExtended,
            version = version,
            targetDuration = targetDuration,
            playlistType = playlistType,
            mediaSequence = mediaSequence,
            endList = endList
        )
    }

    /**
     * 解析加密Key信息
     */
    private fun parseEncryptionKey(line: String, basePath: String): EncryptionKey? {
        try {
            // 解析KEY标签参数
            val params = line.substringAfter("#EXT-X-KEY:").split(",")
            val paramMap = mutableMapOf<String, String>()

            params.forEach { param ->
                val parts = param.split("=", limit = 2)
                if (parts.size == 2) {
                    val key = parts[0].trim()
                    var value = parts[1].trim()

                    // 移除可能的引号
                    if (value.startsWith("\"") && value.endsWith("\"")) {
                        value = value.substring(1, value.length - 1)
                    }

                    paramMap[key] = value
                }
            }

            val method = paramMap["METHOD"] ?: return null

            return when (method.uppercase()) {
                "NONE" -> EncryptionKey(method = "NONE")
                "AES-128" -> {
                    val uri = paramMap["URI"] ?: return null
                    val iv = paramMap["IV"]

                    // 处理相对路径的URI
                    val resolvedUri = resolveUrl(uri, basePath)

                    EncryptionKey(
                        method = "AES-128",
                        uri = resolvedUri,
                        iv = iv,
                        keyFormat = paramMap["KEYFORMAT"],
                        keyFormatVersions = paramMap["KEYFORMATVERSIONS"]
                    )
                }
                "SAMPLE-AES" -> {
                    EncryptionKey(
                        method = "SAMPLE-AES",
                        uri = paramMap["URI"],
                        iv = paramMap["IV"],
                        keyFormat = paramMap["KEYFORMAT"],
                        keyFormatVersions = paramMap["KEYFORMATVERSIONS"]
                    )
                }
                else -> null
            }
        } catch (e: Exception) {
            return null
        }
    }

    /**
     * 解析URL，处理相对路径
     */
    private fun resolveUrl(url: String, basePath: String): String {
        return try {
            if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) {
                url
            } else if (basePath.isNotEmpty()) {
                if (basePath.startsWith("http://") || basePath.startsWith("https://")) {
                    URI(basePath).resolve(url).toString()
                } else {
                    // 处理文件路径
                    File(basePath, url).absolutePath
                }
            } else {
                url
            }
        } catch (e: Exception) {
            url
        }
    }
}

